# -*- coding: utf-8 -*-
import os
import logging
import random
import time
from PIL import Image
from traceback import format_exc
from scrapy.utils.project import get_project_settings
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from zc_core.dao.cookie_dao import CookieDao
from zc_core.plugins.verify_code import VerifyCode

logger = logging.getLogger('login')


class SeleniumLogin(object):
    # 登录地址
    login_url = 'https://cgwzgy.11185.cn/oscp/enterprise/Manage/login.html'
    cookie_white_list = ['centralSessionId', 'JSESSIONID']

    def __init__(self, timeout=60):
        settings = get_project_settings()
        self.max_login_retry = settings.get('MAX_LOGIN_RETRY', 2)
        self.timeout = timeout
        self.accounts = settings.get('ACCOUNTS', [])
        self.option = webdriver.ChromeOptions()
        self.option.add_argument('--headless')
        self.option.add_argument('--no-sandbox')
        # proxy = CachedProxyPool().get_proxy()
        # if proxy:
        #     self.option.add_argument("--proxy-server=http://{}".format(proxy))
        # self.option.add_argument("--proxy-server=http://{}".format('58.218.92.89:4360'))

    def new_chrome(self):
        self.browser = webdriver.Chrome(chrome_options=self.option)
        self.browser.set_window_size(1200, 800)
        self.browser.set_page_load_timeout(self.timeout)

    def login(self):
        try:
            self.new_chrome()
            self.browser.get(self.login_url)

            submit = self.browser.find_element_by_id('submitButton')
            submit.click()
            self.browser.implicitly_wait(5)

            tip = self.browser.find_element_by_id('tipBtn')
            tip.click()

            # 识别验证码
            code = self._verify_code(self.browser.find_element_by_id('random_jpeg'))
            if code:
                # 随机选择账号
                account = random.choice(self.accounts)
                logger.info('login account: %s' % account)

                # 机构类型
                industry_type = self.browser.find_element_by_id("industryType")
                Select(industry_type).select_by_value(account.get('industryType'))
                time.sleep(1)

                # 用户名
                username = self.browser.find_element_by_id("userName")
                username.clear()
                username.send_keys(account.get('userName'))
                time.sleep(1)

                # 密码
                password = self.browser.find_element_by_id("pw")
                password.clear()
                password.send_keys(account.get('pw'))
                time.sleep(5)

                # 验证码
                verify = self.browser.find_element_by_id("randomCode")
                verify.clear()
                verify.send_keys(code)
                time.sleep(15)

                # 登录
                self.browser.execute_script('formValidate();')
                time.sleep(5)

                # 校验
                WebDriverWait(self.browser, 30, ignored_exceptions=TimeoutException).until(
                    EC.presence_of_element_located((By.ID, 'search')))
                cookies = self.browser.get_cookies()
                logger.info('--> cookies: %s' % cookies)

                self.browser.close()
                return cookies
        except Exception as e:
            _ = e
            logger.error(format_exc())
            self.browser.close()
            return list()

    def _verify_code(self, element):
        """
        截取指定元素图片
        :param element: 元素对象
        :return: 无
        """
        """图片路径"""
        settings = get_project_settings()
        base_path = os.path.join(settings.get('OUTPUT_ROOT'), 'verify_code\\')
        if not os.path.exists(base_path):
            os.makedirs(base_path)
        file = os.path.join(base_path, '%s.png' % str(time.strftime('%Y%m%d%H%M%S')))
        self.browser.save_screenshot(file)

        """获取元素坐标"""
        left = element.location['x']
        top = element.location['y']
        width = left + element.size['width']
        height = top + element.size['height']

        """截图保存"""
        picture = Image.open(file)
        picture = picture.crop((left, top, width, height))
        picture.save(file)

        """保存识别结果"""
        code = VerifyCode().verify(file, code_type='1005')
        if code:
            new_file = os.path.join(base_path, '%s.png' % code)
            os.rename(file, new_file)
            return code

    # cookie获取
    def get_cookies(self):
        cookie_dao = CookieDao()
        cookies = cookie_dao.get_cookie()
        if not cookies:
            cookies = self.__get_cookies(0)
            cookie_dao.save_cookie(cookies, expire_time=7200)
        return cookies

    # 最大重试登录获取cookie
    def __get_cookies(self, retry):
        # 登录获取
        arr = self.login()
        if not arr:
            # 失败重试
            if retry <= self.max_login_retry:
                retry = retry + 1
                logger.info('--> 登录失败重试: %s次' % retry)
                return self.__get_cookies(retry)
            else:
                logger.info('--> 放弃失败重试: %s次' % retry)
                return dict()

        # 重组、敏感过滤
        cookies = dict()
        for cookie in arr:
            cookie_key = cookie.get('name')
            if cookie_key in self.cookie_white_list:
                cookies[cookie_key] = cookie.get('value')

        # 校验
        if not cookies or not self._validate_cookie(cookies):
            # 失败重试
            if retry <= self.max_login_retry:
                retry = retry + 1
                logger.info('--> 登录失败重试: %s次' % retry)
                return self.__get_cookies(retry)
            else:
                logger.info('--> 放弃失败重试: %s次' % retry)
                return dict()

        logger.info('--> 登录成功: %s' % retry)
        return cookies

    # cookie校验
    def _validate_cookie(self, cookies):
        for must_key in self.cookie_white_list:
            # 必要字段校验
            if not cookies or (must_key not in cookies) or (cookies.get(must_key) is None) or (
                    cookies.get(must_key) is ''):
                logger.info('--> Cookie未通过校验: key=%s, cookie=%s' % (must_key, cookies))
                return False

        return True


if __name__ == '__main__':
    login = SeleniumLogin()
    login.get_cookies()
